package com.lfy.kcat.user.controller;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * @author leifengyang
 * @version 1.0
 * @date 2025/9/20 14:07
 * @description:
 */
@Slf4j
@RequestMapping("/api")
@RestController
public class RedissonTestController {

    @Autowired
    RedissonClient redissonClient;

    public void lockaaa(){
        //加解锁必须成对出现
        RLock lock = redissonClient.getLock("mylock");

        lock.lock();
        //子业务
        lock.lock();

        //子业务
        lock.lock();
        lock.unlock();

        lock.unlock();


        lock.unlock();
    }

    @GetMapping("/read")
    public String read() throws InterruptedException {
        // 百万并发都读
        RReadWriteLock hahaLock = redissonClient.getReadWriteLock("hahaLock");
        //读读读读 相当于无锁； 读锁是共享锁
        RLock rLock = hahaLock.readLock();
        rLock.lock();
        log.info("read lock 获取到，正在读数据中...");
        //执行读

        Thread.sleep(3000);

        log.info("read lock 解锁");
        rLock.unlock();


        return "ok";

    }

    @GetMapping("/write")
    public String write() throws InterruptedException {
        RReadWriteLock hahaLock = redissonClient.getReadWriteLock("hahaLock");

        // 读读写读读
        // 写读读
        // 写写读
        // 写锁：排他锁
        RLock rLock = hahaLock.writeLock();

        rLock.lock();
        log.info("write lock 获取到，正在写数据中...");

        Thread.sleep(10000);
        log.info("write lock 解锁");
        rLock.unlock();
        return "ok";

    }


    @GetMapping("/test/lock")
    public String lock() throws InterruptedException {
        //只要名字一样，就是同一把锁
        RLock lock = redissonClient.getLock("mylock");

        //1、加锁； 阻塞式加锁，加锁成功后，代码执行到下一行
        try {

            log.info("准备获取锁...");
            lock.lock();  //30s 过期时间，自动续期
//            //默认30s，每隔1/3 锁时间，就续满期

            //自动过期时间 10s； 没有了续期功能
//            lock.lock(20, TimeUnit.SECONDS);


            //尝试加锁; 抢一下
            // 尝试加锁; 抢一下
            // waitTime： 限时等待100s（100s内是否能抢到）
            // leaseTime：一旦抢到锁，锁持有多久时间就释放（50s就释放）
//            boolean b = lock.tryLock(100,50,TimeUnit.SECONDS);
//            if(b){
//                //抢到
//            }else{
//                //没抢到
//            }


            log.info("获取锁成功...");
            System.out.println("业务正在进行.....");

            Thread.sleep(10000000);

            System.out.println("业务结束.....");
        }finally {
            //解锁
            log.info("准备释放锁...");
            lock.unlock();
        }
        //执行业务
        return "ok";
    }


    //1分钟访问2次
    @GetMapping("/redisson/aaa")
    public String aaa(){
        //限制
        RRateLimiter aaaLimiter = redissonClient.getRateLimiter("aaaLimiter");

        //尝试获取一个许可
        boolean b = aaaLimiter.tryAcquire();
        if (b){
            return "ok";
        }

        return "流量已达高峰，稍后再试";
    }


    @GetMapping("/ratelimiter/init")
    public String initLimiter(){
        RRateLimiter aaaLimiter = redissonClient.getRateLimiter("aaaLimiter");

        //1分钟2次
        aaaLimiter.trySetRate(RateType.OVERALL,2, 1, RateIntervalUnit.MINUTES);
        return "init ok";
    }


    //分布式集合

    @GetMapping("/redisson/set")
    public String set(){
        //只要key一样，就是一个集合
        RMap<Object, Object> grades = redissonClient.getMap("grades");

        grades.put("leifengyang",100);
        grades.put("zhangsan", 90);

        return "ok";
    }

    @GetMapping("/redisson/get")
    public String get(){
        RMap<Object, Object> grades = redissonClient.getMap("grades");

       return grades.get("leifengyang").toString();
    }

}
